package com.tianyu.inspection.configuration;

import com.alibaba.fastjson2.JSON;
import com.tianyu.inspection.common.Constants;
import com.tianyu.inspection.common.enums.RoState;
import com.tianyu.inspection.init.ApplicationInit;
import com.tianyu.inspection.entity.User;
import com.tianyu.inspection.entity.vo.Ro;
import com.tianyu.inspection.service.api.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**********************************
 * @Author YSW
 * @Description
 * @Date 2020.12.17 - 14:32
 **********************************/

@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Resource
    private IUserService userService;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedHeaders("*").allowCredentials(false).allowedMethods("*").maxAge(1800).allowedOrigins("*");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(new HandlerInterceptor() {

            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                    return true;
                }
                Ro<Void> ro = new Ro<>();
                response.setHeader("Content-Type", "application/json;charset=utf-8");
                String id = request.getHeader("u-uid");
                log.info("用户["+id+"] "+request.getMethod() + " - " + request.getRequestURI() + " - " + request.getQueryString());
                String token = request.getHeader("u-token");
                String projectId = request.getHeader("u-projectId");
                String version = request.getHeader("u-version");
                String platform = request.getHeader("u-platform");
                if (Objects.isNull(id) || Objects.isNull(projectId) || Objects.isNull(token)) {
                    ro.setResultEnum(RoState.USER_LOGOUT_ERROR).setMessage("缺少头信息[u-uid / u-token / u-projectId]");
                    response.getWriter().write(JSON.toJSONString(ro));
                    return false;
                }
                if ("".equals(id) || !Constants.NUMBER_PATTERN.matcher(id).matches()) {
                    ro.setResultEnum(RoState.USER_LOGOUT_ERROR).setMessage("头信息[u-uid]非数字类型");
                    response.getWriter().write(JSON.toJSONString(ro));
                    return false;
                }
                User loginUser = userService.cacheUserById(Integer.valueOf(id));
                if (Objects.nonNull(loginUser)) {
                    String redisToken = loginUser.getToken();
                    Integer redisProjectId = loginUser.getProjectId();
                    if (Objects.nonNull(redisProjectId)) {
                        if (!Integer.valueOf(projectId).equals(redisProjectId)) {
                            ro.setResultEnum(RoState.USER_LOGOUT_ERROR).setMessage("用户projectId错误");
                            response.getWriter().write(JSON.toJSONString(ro));
                            return false;
                        }
                    }
                    if (Objects.nonNull(redisToken)) {
                        if (token.equals(redisToken)) {
                            Integer roleId = loginUser.getRole().getId();
                            request.setAttribute("roleId", roleId);
                            if (roleId == 1 || authorityVerification(request.getRequestURI(), roleId)) {
                                Constants.USER_THREAD_LOCAL.set(loginUser);
                                return true;
                            } else {
                                ro.setResultEnum(RoState.USER_LOGOUT_ERROR).setMessage("接口不存在,或无权限访问");
                                response.getWriter().write(JSON.toJSONString(ro));
                                return false;
                            }
                        } else {
                            ro.setResultEnum(RoState.USER_LOGOUT_ERROR).setMessage("用户未登录状态已过期");
                            response.getWriter().write(JSON.toJSONString(ro));
                            return false;
                        }
                    } else {
                        ro.setResultEnum(RoState.USER_LOGOUT_ERROR).setMessage("用户Token未存储");
                        response.getWriter().write(JSON.toJSONString(ro));
                        return false;
                    }
                } else {
                    ro.setResultEnum(RoState.USER_LOGOUT_ERROR).setMessage("用户未登录");
                    response.getWriter().write(JSON.toJSONString(ro));
                    return false;
                }
            }
        });
        registration.addPathPatterns("/**")
                .excludePathPatterns("/swagger-ui/**")
                .excludePathPatterns("/error")
                .excludePathPatterns("/swagger-resources/**")
                .excludePathPatterns("/v2/api-docs/**")
                .excludePathPatterns("/api/2.0/user/login")
                .excludePathPatterns("/api/2.0/flyTask/report/**")
                .excludePathPatterns("/api/2.0/clientSoftware/version/**")
                .excludePathPatterns("/api/2.0/clientSoftware/latestVersion")
                .excludePathPatterns("/api/2.0/clientSoftware/test/latestVersion")
                .excludePathPatterns("/api/2.0/clientSoftware/android/latestVersion")
                .excludePathPatterns("/api/2.0/clientSoftware/android/test/latestVersion");
    }

    private boolean authorityVerification(String requestUri, Integer id) {
        requestUri = requestUri.replaceAll("/+", "/");
        int lastIndex = requestUri.lastIndexOf("/");
        String substring = requestUri.substring(requestUri.lastIndexOf("/") + 1);
        if (ApplicationInit.REQUEST_PATH_PERMISSION.containsKey(requestUri)) {
            return ApplicationInit.REQUEST_PATH_PERMISSION.get(requestUri) >= id;
        }
        if (Constants.NUMBER_PATTERN.matcher(substring).matches()) {
            String requestUri2 = requestUri.substring(0, lastIndex) + "/{id}";
            if (ApplicationInit.REQUEST_PATH_PERMISSION.containsKey(requestUri2)) {
                return ApplicationInit.REQUEST_PATH_PERMISSION.get(requestUri2) >= id;
            }
        }
        return false;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/js/**").addResourceLocations("classpath:/inspect-line/js/");
        registry.addResourceHandler("/leaflet/**").addResourceLocations("classpath:/inspect-line/leaflet/");
        registry.addResourceHandler("/index.html").addResourceLocations("classpath:/inspect-line/index.html");
    }
}
